import cv2
import numpy as np
import matplotlib
# matplotlib.use('TkAgg')  # TkAgg或 'Qt5Agg', 'WXAgg' 等
import matplotlib.pyplot as plt

import sys,io,os
#sys.stdout = io.TextIOWrapper(sys.stdout.buffer, encoding='utf-8')
segCount=40
ms=['laplacian','sobel','tenengrad']

currMethod=ms[1]

# text="清晰度"
# print(text.encode('utf-8').decode('utf-8'),text)

def calculate_clarity_roi(image_path, roi_coords, method="laplacian"):
    """
    计算图像指定区域的清晰度
    :param image_path: 图像路径
    :param roi_coords: ROI坐标 (x1, y1, x2, y2)，对应左上角(x1,y1)、右下角(x2,y2)
    :param method: 评估方法，可选 "laplacian"（默认）、"sobel"、"tenengrad"
    :return: 清晰度指标（值越大越清晰）
    """

    # 1. 读取图像（保留原始通道，后续按需灰度化）
    img = cv2.imread(image_path)
    if img is None:
        raise ValueError("无法读取图像，请检查路径是否正确")
    
    # 2. 提取ROI（OpenCV格式：y1:y2, x1:x2）
    x1, y1, x2, y2 = roi_coords
    # 校验ROI坐标合法性（避免超出图像尺寸）
    h, w = img.shape[:2]
    if x1 < 0 or x2 > w or y1 < 0 or y2 > h:
        raise ValueError(f"ROI坐标超出图像范围！图像尺寸：(w={w}, h={h})，ROI：{roi_coords}")
    roi = img[y1:y2, x1:x2]
    
    # 3. 转为灰度图（所有方法均需单通道输入）
    gray_roi = cv2.cvtColor(roi, cv2.COLOR_BGR2GRAY)
    
    # 4. 根据方法计算清晰度指标
    if method == "laplacian":
        # 拉普拉斯方差法：使用3x3拉普拉斯算子（检测二阶导数）
        laplacian = cv2.Laplacian(gray_roi, cv2.CV_64F)  # 用64F避免溢出
        clarity = laplacian.var()  # 方差越大，清晰度越高
    
    elif method == "sobel":
        # Sobel梯度法：计算x+y方向梯度的均值
        sobel_x = cv2.Sobel(gray_roi, cv2.CV_64F, 1, 0, ksize=3)
        sobel_y = cv2.Sobel(gray_roi, cv2.CV_64F, 0, 1, ksize=3)
        sobel_mag = np.sqrt(sobel_x**2 + sobel_y**2)  # 梯度幅度
        clarity = np.mean(sobel_mag)  # 均值越大，清晰度越高
    
    elif method == "tenengrad":
        # Tenengrad梯度法：计算Sobel梯度的平方和均值（抗噪声更强）
        sobel_x = cv2.Sobel(gray_roi, cv2.CV_64F, 1, 0, ksize=3)
        sobel_y = cv2.Sobel(gray_roi, cv2.CV_64F, 0, 1, ksize=3)
        tenengrad = sobel_x**2 + sobel_y**2
        clarity = np.mean(tenengrad)  # 均值越大，清晰度越高
    
    else:
        raise ValueError("方法不支持！可选：'laplacian'、'sobel'、'tenengrad'")
    
    return clarity, roi  # 返回清晰度指标和ROI图像（用于可视化）

def GetImageMTF(image_path:str)->list:
    ret=[]
    roi_coords = (0, 0, 44, 100)  # (x1, y1, x2, y2)：左上角到右下角
    method = "laplacian"  # 选择评估方法
    method=currMethod
    # segCount=5

    img=cv2.imread(image_path)
    print(image_path)
    h,w=img.shape[:2]
    segHeight=(int)(h/segCount)

    
    
    # 2. 计算清晰度
    try:

        for i in range(0,segCount):
            roi_coords=(0,i*segHeight,w,(i+1)*segHeight)
            clarity_score, roi = calculate_clarity_roi(image_path, roi_coords, method)
            print(f"{method} area:{(roi_coords[1],roi_coords[3])} 清晰度:{clarity_score:.2f}")
            # ret.append(f'{clarity_score:.2f}')
            ret.append(round(clarity_score,2))
            
    except Exception as e:
        print(f"错误：{e}")
    return ret

def append_content_to_file(filename, content, mode='a', encoding='utf-8'):
    """
    创建新文件并写入内容
    :param filename: 文件名（可包含路径）
    :param content: 写入内容（字符串或字节）
    :param mode: 写入模式 'w'-文本写入 / 'wb'-二进制写入
    :param encoding: 文本编码（默认utf-8）
    :return: 成功返回True，失败返回False
    """
    try:
        dir_path = os.path.dirname(filename)
        if dir_path and not os.path.exists(dir_path):
            os.makedirs(dir_path)
            
        # with open(filename, mode, encoding=encoding if 'b' not in mode else None) as f:
        with open(filename, mode, encoding=encoding) as f:
            f.write(content)
            f.write('\r\n')
        return True
    except Exception as e:
        print(f"文件写入失败: {str(e)}")
        return False

# ---------------------- 示例：计算指定区域清晰度 ----------------------
if __name__ == "__main__":
    # append_content_to_file(r'c:\1.txt',"10,20,30,50")
    # append_content_to_file(r'c:\1.txt',"20,10,30,50")
    # print(v,type(v[0]))
    # line=','.join(v)
    # append_content_to_file(r'c:\1.csv',line)
    import tkinter as tk
    from tkinter import messagebox

    root = tk.Tk()
    root.withdraw()  # 隐藏主窗口
    messagebox.showinfo("测试", "Tkinter 工作正常！")
    root.destroy()

    
    plt.figure(num='TDI清晰度输出')
    plt.xlabel("X axis", fontsize=12) 
    plt.ylabel("MTF value", fontsize=12) 
    # xaxis=[1, 2, 3,4,5]
    xaxis=list(range(1, segCount+1,1))
    print(xaxis)
	

    picdir="y:\\pic\\"+sys.argv[1]
    # picdir=os.path.abspath(os.curdir)+"\\"+sys.argv[1]
	
    print(sys.argv[0],sys.argv[1],picdir)
    

    fs= os.listdir(picdir)
    for i in fs:
        if i.__contains__('bmp'):
            fn=i.split('.')[0]

            v=GetImageMTF(f"{picdir}\\{i}")
            plt.plot(xaxis,v,label=f"offset_{fn}")
        
    # plt.plot(xaxis,v,label="line1")
    # plt.plot(xaxis,[1500,2235,2425,2233,1456],label="line2")
    plt.legend()
    plt.show()

    pass
    